#!/bin/sh

# shellcheck disable=SC1091
. /usr/libexec/os-helpers-fs

FREESPACE_LIMIT=10

resindataexpander_enabled() {
    # On flasher avoid expanding partition
    # shellcheck disable=SC2154
    if [ "$bootparam_flasher" = "true" ]; then
        info "Flasher detected. Avoiding expand partition mechanism."
        return 1
    fi

    datapart=$(get_state_path_from_label "resin-data")
    datapartdev=$(basename $(readlink -f "${datapart}"))
    if is_part_encrypted "${datapartdev}"; then
        if [ "$(ls /sys/class/block/${datapartdev}/slaves | wc -l)" != "1" ]; then
            # This is just a disaster circuit breaker, it should never happen
            fail "Unable to determine parent partition for ${datapartdev}"
        fi

        # We have asserted that there is a single slave device
        datapartdev=$(ls "/sys/class/block/${datapartdev}/slaves")
    fi
    datadev=$(lsblk "/dev/${datapartdev}" -d -n -o PKNAME)
    pttype=$(get_part_table_type "/dev/${datadev}")

    if ! wait4file "$datapart" "300"; then
        error "Timeout while waiting for data partition to be detected. Data partition expansion will not be tried."
        return 1
    fi

    # If the secondary GPT is not the end of the disk, parted will ask
    # to fix it. If GPT is already fixed, nothing else happens.
    # This currently only works in interactive mode
    if [ "${pttype}" = "gpt" ]; then
        echo "Fix" | parted  ---pretend-input-tty /dev/${datadev} print 2>&1 > /dev/null
        partprobe
        sync
            if sgdisk -v /dev/${datadev} 2>&1 | grep -q "corrupt GPT"; then
                sgdisk --backup=/run/gpt.bkp /dev/${datadev}
                sgdisk --load-backup=/run/gpt.bkp /dev/${datadev}
            fi
    fi

    return 0
}

resindataexpander_run() {
    part_number=$(cat /sys/class/block/"${datapartdev}"/partition)

    # lsblk works on block devices only
    for freespace in $(parted -m "/dev/$datadev" unit MiB print free | grep free | cut -d: -f4 | sed 's/MiB//g'); do
        if [ "$(echo "$freespace" \> $FREESPACE_LIMIT | bc -l)" = "1" ]; then
            # msdos partition types with more than 4 partitions need to
            # convert the 4th in an extended partition
            if [ "${pttype}" = "msdos" ] && [ "${part_number}" -gt 4 ]; then
                info "resindataexpander: Expand extended partition... "
                parted -s "/dev/$datadev" -- resizepart 4 -1s
                info "resindataexpander: Finished expanding extended partition."
            fi
            info "resindataexpander: Expand data partition... "
            parted -s "/dev/$datadev" -- resizepart "${part_number}" 100%
            info "resindataexpander: Finished expanding data partition."
            partprobe
            sync

            # We return when we've done the expansion
            info "Data partition at $datapart expanded."
            break
        fi
    done

    # Expand only dm-crypt device as LUKS partitions are autoexpanded on cryptsetup open
    if is_part_encrypted "${datapartdev}" && ! is_luks "${datapartdev}"; then
        _label=$(lsblk -nlo label,type "/dev/${datapartdev}" | grep dm | awk '{print $1}')
        if [ -n "${_label}" ]; then
            _size=$(lsblk -nb -o NAME,SIZE,TYPE "/dev/${datapartdev}" | grep part | awk '{print $2}')
            _sector_size=$(lsblk -o NAME,PHY-SEC,TYPE "/dev/${datapartdev}" | grep part | awk '{print $2}')
            _sectors=$(expr "${_size}" / "${_sector_size}")
            _current_sectors=$(dmsetup table "${_label}" | awk '{print $2}')
            if [ "${_sectors}" != "${_current_sectors}" ]; then
                _ntable=$(dmsetup table "${_label}" | awk -v sectors="${_sectors}" '{$2=sectors; print}')
                dmsetup suspend "${_label}"
                dmsetup reload "${_label}" --table "${_ntable}"
                dmsetup resume "${_label}"
                info "resindataexpander: ${_label} DM device expanded "
            fi
        else
            error "Failed to expand partition ${datapartdev}"
        fi
    fi

    # Expand filesystem
    info "resindataexpander: Expand ext4 filesystem on ${datapart}"
    resize2fs -f "${datapart}"
    sync
}
